package com.gitee.kamismile.stone.basic.data.domain.sysdic.service.impl;

import com.gitee.kamismile.stone.basic.data.application.rep.DictionaryDefineRep;
import com.gitee.kamismile.stone.basic.data.application.req.query.dic.SysDictionaryDefineQuery;
import com.gitee.kamismile.stone.basic.data.domain.sysdic.aggregate.enums.StateEnum;
import com.gitee.kamismile.stone.basic.data.domain.sysdic.repository.entity.SysDictionary;
import com.gitee.kamismile.stone.basic.data.domain.sysdic.repository.entity.SysDictionaryDefine;
import com.gitee.kamismile.stone.basic.data.domain.sysdic.repository.persistence.ISysDictionaryPersistence;
import com.gitee.kamismile.stone.basic.data.domain.sysdic.service.ISysDictionaryDomainService;
import com.gitee.kamismile.stone.basic.data.infrastructure.enums.DicErrorEnum;
import com.gitee.kamismile.stone.basic.data.infrastructure.repository.r2Repository.sysdic.repository.SysDictionaryDefineRepository;
import com.gitee.kamismile.stone.basic.data.infrastructure.utils.CriteriaQueryBuilder;
import com.gitee.kamismile.stone.basic.data.infrastructure.utils.PageQueryBuilder;
import com.gitee.kamismile.stone.basic.data.infrastructure.utils.QueryBuilder;
import com.gitee.kamismile.stone.commmon.exception.BusinessException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.r2dbc.core.R2dbcEntityTemplate;
import org.springframework.data.relational.core.query.Criteria;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

@Service
public class SysDictionaryDomainServiceImpl implements ISysDictionaryDomainService {

    @Autowired
    private  R2dbcEntityTemplate template;

    @Autowired
    private ISysDictionaryPersistence iSysDictionaryPersistence;

    @Autowired
    private SysDictionaryDefineRepository sysDictionaryDefineRepository;

    @Override
    public Mono<SysDictionary> findDicDefineByAlias(String alias, Integer nTenantId) {
        Criteria criteria = CriteriaQueryBuilder.builder()
                .eqIgnoreEmpty("sAlias", alias)
                .inIgnoreEmpty("nTenantId", new Object[]{0,nTenantId})
                .create();
       return iSysDictionaryPersistence.findOne(criteria);
    }

    @Override
    public Mono<SysDictionary> saveOrUpdate(SysDictionary sysDictionary) {
     return iSysDictionaryPersistence.save(sysDictionary);
    }


    public Mono<Page<SysDictionary>> findAllBy(int page, int size,
                                   Criteria criteria) {
        Pageable pageable = PageRequest.of(page, size,Sort.by(Sort.Direction.DESC, "nSysDictionaryId"));
        return new PageQueryBuilder<>(template, SysDictionary.class)
                .where(criteria)
                .pageable(pageable)
                .apply();

    }

    public Mono<Page<SysDictionaryDefine>> findDicDefinePageByDicId(int page, int size,
                                                                    Criteria criteria) {
        Pageable pageable = PageRequest.of(page, size);
        return new PageQueryBuilder<>(template, SysDictionaryDefine.class)
                .where(criteria)
                .pageable(pageable)
                .apply();

    }

    @Override
    public Flux<DictionaryDefineRep> findDicDefineByAlias(SysDictionaryDefineQuery query) {
        return sysDictionaryDefineRepository.findDicDefineAllByAlias(query.getAlias(), query.getnTenantId());    }

    @Override
    public Mono<SysDictionaryDefine> saveOrUpdate(SysDictionaryDefine sysDictionaryDefine) {
        return sysDictionaryDefineRepository.save(sysDictionaryDefine);
    }

    @Override
    public Mono<Void> deleteDicById(Integer nSysDictionaryId, Integer nTenantId) {
        return iSysDictionaryPersistence.deleteDicById(nSysDictionaryId, nTenantId);
    }

    @Override
    public Mono<Void> deleteDicDefineById(Long nSysDictionaryDefineId, Integer nTenantId) {
//        SysDictionaryDefine sysDictionaryDefine=new SysDictionaryDefine();
//        sysDictionaryDefine.setnSysDictionaryDefineId(nSysDictionaryDefineId);
//        sysDictionaryDefine.setnState(StateEnum.Delete.getCode());
//        return sysDictionaryDefineRepository.save(sysDictionaryDefine);
        return sysDictionaryDefineRepository.deleteById(nSysDictionaryDefineId);
    }

    @Override
    public Mono<SysDictionary> findAndCheckSysDicById(Integer nSysDictionaryId, Integer nTenantId) {
        return findSysDicById(nSysDictionaryId, nTenantId)
                .switchIfEmpty(Mono.defer(() -> Mono.error(
                        new BusinessException(
                                DicErrorEnum.DicNotFound.getCode(),
                                DicErrorEnum.DicNotFound.getMessage()
                        ))));
    }

    private Mono<SysDictionary> findSysDicById(Integer nSysDictionaryId, Integer nTenantId) {
        Criteria criteria = CriteriaQueryBuilder.builder()
                .eqIgnoreEmpty("nSysDictionaryId", nSysDictionaryId)
                .inIgnoreEmpty("nTenantId", new Object[]{nTenantId})
                .create();
        return iSysDictionaryPersistence.findOne(criteria);
    }

    @Override
    public Mono<SysDictionaryDefine> findAndCheckSysDicDefineById(Long nSysDictionaryDefineId, Integer nTenantId) {
        return findSysDicDefineById(nSysDictionaryDefineId, nTenantId)
                .switchIfEmpty(Mono.defer(() -> Mono.error(
                        new BusinessException(
                                DicErrorEnum.DicDefNotFound.getCode(),
                                DicErrorEnum.DicDefNotFound.getMessage()
                        ))));
    }

    private Mono<SysDictionaryDefine> findSysDicDefineById(Long nSysDictionaryDefineId, Integer nTenantId) {
        Criteria criteria = CriteriaQueryBuilder.builder()
                .eqIgnoreEmpty("nSysDictionaryDefineId", nSysDictionaryDefineId)
                .inIgnoreEmpty("nTenantId", new Object[]{nTenantId})
                .create();
        return new QueryBuilder<>(template, SysDictionaryDefine.class)
                .where(criteria)
                .apply().one();
    }
}
